/*
 * $RCSfile: TablePanel.java,v $
 * $Revision: 1.1 $
 * $Date: 2009-10-12 $
 *
 * Copyright (C) 2005 Skin, Inc. All rights reserved.
 *
 * This software is the proprietary information of Skin, Inc.
 * Use is subject to license terms.
 */
package com.skin.generate.gui.table;

import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.skin.generate.GenericGenerator;
import com.skin.generate.Template;
import com.skin.generate.gui.Constant;
import com.skin.generate.gui.GeneratorDialog;
import com.skin.generate.gui.LocalStorage;
import com.skin.generate.gui.SwingManager;
import com.skin.generate.gui.container.BaseFrame;
import com.skin.generate.gui.container.BasePanel;
import com.skin.generate.gui.event.ClickListener;
import com.skin.generate.gui.event.ListClickListener;
import com.skin.generate.gui.util.SqlFile;
import com.skin.generate.gui.util.TableUtil;
import com.skin.generate.gui.util.TemplateUtil;
import com.skin.webcat.database.Column;
import com.skin.webcat.database.Table;
import com.skin.webcat.util.StringUtil;

/**
 * <p>Title: TablePanel</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2006</p>
 * @author xuesong.net
 * @version 1.0
 */
public class TableEditPanel extends BasePanel {
    private static final long serialVersionUID = 1L;
    Table table;
    JTable jTable;
    JButton codeButton;
    JButton saveButton;
    JButton refreshButton;
    TableEditModel tableModel;
    GeneratorDialog generatorDialog;
    static final Logger logger = LoggerFactory.getLogger(TableEditPanel.class);

    /**
     * @param frame
     */
    public TableEditPanel(BaseFrame frame) {
        super(frame);
        this.init(frame);
    }

    /**
     * @param frame
     */
    public void init(BaseFrame frame) {
        JScrollPane jScrollPane = new JScrollPane();
        jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        jScrollPane.setViewportView(this.getJTable());

        this.setLayout(new java.awt.BorderLayout());
        this.add(getJToolBar(), java.awt.BorderLayout.NORTH);
        this.add(jScrollPane, java.awt.BorderLayout.CENTER);
    }

    /**
     * @param params
     */
    @Override
    public void load(Map<String, Object> params) {
        Table table = getTable(params);
        this.setTable(table);
    }

    /**
     * @param params
     * @return Table
     */
    private Table getTable(Map<String, Object> params) {
        Table table = (Table)(params.get("table"));

        if(table != null) {
            return table;
        }

        String connectionName = (String)(params.get("name"));
        String tableName = (String)(params.get("tableName"));

        if(connectionName != null && tableName != null) {
            try {
                return TableUtil.getTable(connectionName, tableName);
            }
            catch(Exception e) {
                logger.error(e.getMessage(), e);
                error(e);
            }
            return null;
        }

        String path = (String)(params.get("path"));

        if(path != null) {
            try {
                return SqlFile.getTable(path, tableName);
            }
            catch(Exception e) {
                logger.error(e.getMessage(), e);
                error(e);
            }
            return null;
        }
        return null;
    }

    /**
     * @return JToolBar
     */
    JToolBar getJToolBar() {
        JToolBar jToolBar = new JToolBar();
        jToolBar.setFloatable(false);
        jToolBar.setBorder(new EmptyBorder(4, 4, 4, 4));
        jToolBar.add(this.getCodeButton());
        jToolBar.add(this.getSaveButton());
        return jToolBar;
    }

    JButton getCodeButton() {
        if(this.codeButton == null) {
            this.codeButton = new JButton("生成代码");
            this.codeButton.setFont(SwingManager.getDefaultFont());
            this.codeButton.setMargin(new Insets(0, 10, 0, 10));
            this.codeButton.setBorder(new EmptyBorder(5, 5, 5, 5));

            this.codeButton.addActionListener(new ClickListener() {
                @Override
                public void click(ActionEvent actionEvent) {
                    showGenerateDialog();
                }
            });
        }
        return this.codeButton;
    }
                                                
    JButton getSaveButton() {
        if(this.saveButton == null) {
            this.saveButton = new JButton("保 存");
            this.saveButton.setFont(SwingManager.getDefaultFont());
            this.saveButton.setMargin(new Insets(0, 10, 0, 10));
            this.saveButton.setBorder(new EmptyBorder(5, 5, 5, 5));

            this.saveButton.addActionListener(new ClickListener(){
                @Override
                public void click(ActionEvent actionEvent) {
                    saveTableAsXml();
                }
            });
        }
        return this.saveButton;
    }

    JButton getRefreshButton() {
        if(this.refreshButton == null) {
            this.refreshButton = new JButton("刷 新");
            this.refreshButton.setFont(SwingManager.getDefaultFont());
            this.refreshButton.setMargin(new Insets(0, 10, 0, 10));
            this.refreshButton.setBorder(new EmptyBorder(5, 5, 5, 5));

            this.refreshButton.addActionListener(new ClickListener() {
                @Override
                public void click(ActionEvent actionEvent) {
                    reload();
                }
            });
        }
        return this.refreshButton;
    }

    /**
     * @return JTable
     */
    protected JTable getJTable() {
        if(this.tableModel == null) {
            this.tableModel = new TableEditModel();
        }

        if(this.jTable == null) {
            this.jTable = new JTable(this.tableModel);

            ListClickListener listClickListener = new ListClickListener() {
                @Override
                public void click(ListSelectionEvent e) {
                    if(e.getValueIsAdjusting() == false) {
                        setEditing();
                    }
                }
            };

            this.jTable.getSelectionModel().addListSelectionListener(listClickListener);
            this.jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            this.jTable.setRowHeight(24);
        }
        return this.jTable;
    }

    /**
     * @param text
     * @return JLabel
     */
    public JLabel getJLabel(String text) {
        JLabel label = new JLabel(text);
        label.setFont(SwingManager.getDefaultFont());
        return label;
    }

    /**
     * @param table
     */
    public void setTable(Table table) {
        this.table = table;

        if(this.table == null) {
            Object[][] data = new Object[0][0];
            this.codeButton.setEnabled(true);
            this.tableModel.setData(data);
            this.jTable.updateUI();
            return;
        }

        try {
            Object[][] data = TableUtil.getColumns(table);
            this.codeButton.setEnabled(true);
            this.tableModel.setData(data);
            this.jTable.updateUI();
            this.setEditing();
        }
        catch(Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * set editing
     */
    public void setEditing() {
        int rowCount = this.jTable.getRowCount();
        int selectedRow = this.jTable.getSelectedRow();

        if(rowCount < 1) {
            return;
        }

        if(selectedRow < 0) {
            selectedRow = 0;
        }

        if(selectedRow > (rowCount - 1)) {
            selectedRow = rowCount - 1;
        }
        this.jTable.setRowSelectionInterval(selectedRow, selectedRow);
        this.jTable.editCellAt(this.jTable.getSelectedRow(), 2);
    }

    /**
     * @return Table
     */
    public Table getTable() {
        if(this.table == null) {
            return null;
        }

        for(int i = 0; i < this.jTable.getRowCount(); i++) {
            String columnName = (String)this.jTable.getValueAt(i, 1);
            String fieldName = (String)this.jTable.getValueAt(i, 2);
            String javaTypeName = (String)this.jTable.getValueAt(i, 4);
            Boolean nullable = (Boolean)this.jTable.getValueAt(i, 8);

            if(!columnName.equals(fieldName)) {
                Column column = this.table.getColumn(columnName);

                if(column != null) {
                    column.setNullable(nullable);
                    column.setVariableName(fieldName);
                    column.setJavaTypeName(javaTypeName);
                    column.setMethodSetter("set" + StringUtil.camel(fieldName));
                    column.setMethodGetter("get" + StringUtil.camel(fieldName));
                }
            }
        }
        return this.table;
    }

    void showGenerateDialog() {
        if(this.generatorDialog == null) {
            this.generatorDialog = new GeneratorDialog(this.frame, Constant.APP_NAME, true);
        }

        Table table = this.getTable();

        if(table == null) {
            this.message("请先选择一个表！");
            return;
        }

        this.generatorDialog.setBatchMode(false);
        this.generatorDialog.setTableName(table.getTableName());
        this.generatorDialog.setClassName(table.getClassName());
        this.generatorDialog.setRemarks(table.getRemarks());
        this.generatorDialog.setAuthor(System.getProperty("user.name"));
        int returnValue = this.generatorDialog.open();

        if(returnValue != GeneratorDialog.ENSURE) {
            return;
        }

        String className = this.generatorDialog.getClassName();
        boolean wrapper = this.generatorDialog.getWrapper();
        String encoding = this.generatorDialog.getEncoding();
        String author = this.generatorDialog.getAuthor();
        String template = this.generatorDialog.getTemplate();
        String output = this.generatorDialog.getOutputPath();
        table.setClassName(className);

        if(wrapper) {
            TableUtil.setWrapper(table);
        }
        this.generate(table, template, encoding, author, output);
    }

    /**
     * @param table
     * @param templateName
     * @param encoding
     * @param author
     * @param output
     */
    void generate(Table table, String templateName, String encoding, String author, String output) {
        String home = TemplateUtil.getTemplateDirectory();

        try {
            String xml = TableUtil.toXml(table);
            LocalStorage.write(new File(output, table.getClassName() + ".xml").getCanonicalFile(), xml, "utf-8");
            List<Template> templates = TemplateUtil.getTemplateList(templateName);

            if(templates == null || templates.size() < 1) {
                this.error("没有可用的模板！");
                return;
            }

            GenericGenerator generator = new GenericGenerator(home, output);
            generator.setTemplates(templates);
            generator.setEncoding(encoding);
            generator.setAuthor(author);
            generator.generate(table);
            this.message("生成完成: " + new File(output).getCanonicalPath());
        }
        catch(Exception e) {
            e.printStackTrace();
            logger.warn(e.getMessage(), e);
            this.error(e);
        }
    }

    void saveTableAsXml() {
        Table table = this.getTable();

        try {
            String tableName = table.getTableName();
            File file = this.showSaveDialog(StringUtil.camel(tableName) + ".xml");

            if(file != null) {
                if(file.exists() && file.isFile()) {
                    if(this.confirm("文件已经存在, 是否覆盖?")) {
                        LocalStorage.write(file, TableUtil.toXml(table), "utf-8");
                        this.message("文件已经保存至: " + file.getAbsolutePath());
                    }
                }
                else {
                    LocalStorage.write(file, TableUtil.toXml(table), "utf-8");
                    this.message("文件已经保存至: " + file.getAbsolutePath());
                }
            }
        }
        catch(Exception e) {
            this.error(e);
        }
    }

    File showSaveDialog(String fileName) {
        LocalStorage localStorage = this.frame.getLocalStorage();
        String dir = localStorage.getValue(Constant.KEY_CURRENT_DIRECTORY, ".");
        JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("XML & XMLS", "xml", "xmls");
        chooser.setCurrentDirectory(new File(dir));
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        chooser.setFileFilter(filter);

        if(fileName != null) {
            chooser.setSelectedFile(new File(fileName));
        }

        int returnValue = chooser.showSaveDialog(this);
        localStorage.setValue(Constant.KEY_CURRENT_DIRECTORY, chooser.getCurrentDirectory().getAbsolutePath());

        if(returnValue == JFileChooser.APPROVE_OPTION) {
           return chooser.getSelectedFile();
        }
        return null;
    }
}
